- Timestamp:
- Jul 27, 2010, 4:58:07 PM (14 years ago)
- Location:
- trunk/grails-app
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/conf/BuildConfig.groovy
r577 r636 85 85 runtime ('org.apache.lucene:lucene-spellchecker:2.4.1') 86 86 87 runtime ('org.apache.ant:ant:1.7.1') 88 runtime ('org.apache.ant:ant-launcher:1.7.1') 89 87 90 } 88 91 -
trunk/grails-app/i18n/messages.properties
r635 r636 15 15 inventoryItemPictures.import.failure.no.directory=Import directory on server not found. 16 16 inventoryItemPictures.import.failure.to.unzip=Failed to unzip supplied file. 17 inventoryItemPictures.import=Picture Import 18 inventoryItemPictures.import.help=A zip file of pictures (max 100MB) or singles pictures may be imported. Pictures \ 19 must have the same file names as existing inventory items. 17 20 18 21 inventoryItemPurchase.import.success=Inventory item purchases imported. -
trunk/grails-app/services/InventoryItemService.groovy
r635 r636 1 1 import org.codehaus.groovy.grails.commons.ConfigurationHolder 2 import org.apache.commons.lang.WordUtils 2 3 3 4 /** … … 7 8 8 9 boolean transactional = false 10 11 def createDataService 12 13 def sessionFactory 14 def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP 9 15 10 16 /** … … 349 355 350 356 /** 351 * Import inventory pictures from an uploaded zip file .357 * Import inventory pictures from an uploaded zip file or picture. 352 358 * @param request The http request to run getFile against. 353 * Get file should return a zip format file containing the inventory item pictures .359 * Get file should return a zip format file containing the inventory item pictures or a picture file. 354 360 */ 355 361 def importInventoryItemPictures(request) { … … 358 364 def kByteMultiplier = 1000 359 365 def mByteMultiplier = 1000 * kByteMultiplier 360 def fileMaxSize = 500 * mByteMultiplier366 def fileMaxSize = 100 * mByteMultiplier 361 367 362 368 def fail = { Map m -> … … 367 373 // Get file from request. 368 374 def multiPartFile = request.getFile('file') 369 def zipFileName = multiPartFile.originalFilename375 def uploadedFileName = multiPartFile.originalFilename 370 376 371 377 if(!multiPartFile || multiPartFile.isEmpty()) … … 375 381 return fail(code: "default.file.over.max.size", args: [fileMaxSize/mByteMultiplier, "MB"]) 376 382 377 // Check create import dir.383 // Check and create import dir. 378 384 def dir = new File(ConfigurationHolder.config.globalDirs.tempInventoryItemPicturesDirectory) 379 def imageFiles = []380 385 381 386 if(!dir.exists()) … … 386 391 } 387 392 388 // Write zip file to disk. 389 def zipOutputFile = new File(dir.absolutePath + File.separator + zipFileName) 390 multiPartFile.transferTo(zipOutputFile) 391 392 // Use ant to unzip. 393 def ant = new AntBuilder() 394 try { 395 ant.unzip( src: zipOutputFile.absolutePath, 396 dest: dir.absolutePath, 397 overwrite:"true" ) 398 } 399 catch(e) { 400 log.error e 401 return fail(code:'inventoryItemPictures.import.failure.to.unzip') 402 } 403 404 // Recurse through dir building list of imageFiles. 405 def imageFilePattern = ~/[^\s].+(\.(?i)(jpg|png|gif|bmp))$/ 406 407 dir.eachFileMatch(imageFilePattern) { 408 imageFiles << it 393 // Write file to disk. 394 def diskFile = new File(dir.absolutePath + File.separator + uploadedFileName) 395 multiPartFile.transferTo(diskFile) 396 397 // File patterns 398 def zipFilePattern = ~/[^\s].*(\.(?i)(zip))$/ 399 def pictureFilePattern = ~/[^\s].*(\.(?i)(jpg|png|gif|bmp))$/ 400 401 // If file claims to be a zip file then try using ant to unzip. 402 if(diskFile.name.matches(zipFilePattern)) { 403 def ant = new AntBuilder() 404 try { 405 ant.unzip( src: diskFile.absolutePath, 406 dest: dir.absolutePath, 407 overwrite:"true" ) 408 } 409 catch(e) { 410 log.error e 411 return fail(code:'inventoryItemPictures.import.failure.to.unzip') 412 } 413 } 414 415 // Recurse through dir building list of pictureFiles. 416 def pictureFiles = [] 417 dir.eachFileMatch(pictureFilePattern) { 418 pictureFiles << it 409 419 } 410 420 411 421 dir.eachDirRecurse { subDir -> 412 subDir.eachFileMatch(imageFilePattern) { 413 imageFiles << it 414 } 415 } 422 subDir.eachFileMatch(pictureFilePattern) { 423 pictureFiles << it 424 } 425 } 426 427 pictureFiles.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } 416 428 417 429 // Find inventoryItems by name of picture and call savePicture. … … 419 431 def itemName 420 432 def savePictureResult 421 422 for(imageFile in imageFiles) { 423 itemName = imageFile.name[0..-5] 433 def pictureCount = 0 434 def picturesSavedCount = 0 435 436 // Turn off index mirroring. 437 createDataService.stopSearchableIndex() 438 439 for(pictureFile in pictureFiles) { 440 pictureCount++ 441 442 if(pictureCount % 10 == 0) { 443 cleanUpGorm() 444 } 445 446 itemName = WordUtils.capitalize(pictureFile.name[0..-5]) 424 447 inventoryItemInstance = InventoryItem.findByName(itemName) 425 448 if(!inventoryItemInstance) { … … 431 454 continue 432 455 } 433 savePictureResult = savePicture(inventoryItemInstance, imageFile)456 savePictureResult = savePicture(inventoryItemInstance, pictureFile) 434 457 if(savePictureResult.error) 435 458 log.error savePictureResult.error 459 else { 460 picturesSavedCount++ 461 log.info 'InventoryItem picture saved: ' + itemName 462 } 463 } 464 465 // Start mirroring again and rebuild index. 466 createDataService.startSearchableIndex() 467 468 log.info 'InventoryItem pictures saved: ' + picturesSavedCount 469 log.info 'InventoryItem pictures total: ' + pictureCount 470 471 // Cleanup. 472 dir.eachFile() { 473 if(it.isDirectory()) 474 it.deleteDir() 436 475 else 437 log.info 'InventoryItem picture saved: ' + itemName476 it.delete() 438 477 } 439 478 … … 443 482 } // importInventoryItemPictures 444 483 484 /** 485 * This cleans up the hibernate session and a grails map. 486 * For more info see: http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/ 487 * The hibernate session flush is normal for hibernate. 488 * The map is apparently used by grails for domain object validation errors. 489 * A starting point for clean up is every 100 objects. 490 */ 491 def cleanUpGorm() { 492 def session = sessionFactory.currentSession 493 session.flush() 494 session.clear() 495 propertyInstanceMap.get().clear() 496 } 497 445 498 } // end class -
trunk/grails-app/views/inventoryItemDetailed/importInventoryItemPictures.gsp
r635 r636 18 18 <tr class="prop"> 19 19 <td valign="top" class="name"> 20 <label for="file"> Directory:</label>20 <label for="file">File:</label> 21 21 </td> 22 22 <td valign="top" class="value"> 23 23 <input type="file" id="file" name="file" size="40"/> 24 <g:helpBalloon code="inventoryItemPictures.import" /> 24 25 </td> 25 26 </tr>
Note: See TracChangeset
for help on using the changeset viewer.