I checked if fineuploader worked on an iPad, and it does mostly, but the iPad only gets a single file "image.jpg" returned, so every file that's uploaded keeps overwriting the previous file. (Or it just uploads one file)
In any case, can this behavior be fixed on either Chrome or Safari on an iPad?
We are using library to uploaded images for different business requirement and its works like dream. thanks for developing this one.
Krishna
here is my code:
I am creating endpoint dynamically and uploading files for different folders. Its getting uploaded for other platform except iOS.
$(document).ready(function () {
$('#s3-fileuploader').fineUploader({
request: {
endpoint: '',
inputName: 'filename',
forceMultipart: true,
paramsInBody: true,
params: {},
},
failedUploadTextDisplay: {
mode: 'custom',
maxChars: 40,
responseProperty: 'error',
enableTooltip: true
},
cors: {
expected: true, //all requests are expected to be cross-domain requests
sendCredentials: false, //if you want cookies to be sent along with the request
allowXdr: true
},
autoUpload: true,
multiple: true,
debug: true,
text: {
uploadButton: '<i class="icon-plus icon-white">Select Files</i> '
},
deleteFile: {
enabled: false,
forceConfirm: true,
},
validation: {
// allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'],
itemLimit: 75
}
}).on('submit', function (event, id, name) {
$(this).fineUploader('setEndpoint', endPoint); //set endpoint
}).on('complete', function (event, id, fileName, response) {
var $deleteEl = $(
'<span class="delete"> <a href="javascript:;" onclick="deleteFile(\'' +
response.deleteFileUrl + '\',\'' + id +
'\')">Delete</a></span> ');
//when you delete element is clicked, call the "deleteFile" API method, passing in that file's ID
if (response.success) {
$(".qq-uploader").append(
'<div class="highlight" style="margin-top:8px;margin-right:8px;float:left;width:180px;height:194px; box-shadow:1px 0 0 #F3F3F3, 0 1px 0 #E4E4E4, 0 -1px 0 #F3F3F3, -1px 0 0 #F3F3F3" class="thumb" id="thumb_' +
id + '"></div>');
//get file name from responce
var filename = getFileName(response.getThumbnailUrl);
//get file extension now
var fileExt = filename.split('.').pop().toLowerCase();
//create array of all available extenions images
var exts = ["csv", "doc", "docx", "xls", "zip", "pdf",
"txt"
];
//check if its a image
if (fileExt == 'jpeg' || fileExt == 'jpg' || fileExt ==
'png' || fileExt == 'gif' || fileExt == 'tiff' ||
fileExt == 'tif' || fileExt == 'bmp' || fileExt ==
'wbmp') {
//myother logic
}
}
});
});
This is due to the design of iOS, not Fine Uploader. See, iOS names the files for you -- "image.jpg" to be exact.
Fine Uploader mitigates this problem by generating a level 4 UUID and sending that along with the upload request. The parameter to look for in the request body is qquuid.
I'm guessing your server is saving files based on their filename only. A more robust solution would be to use a combination of the file's UUID and filename to ensure users are not overwriting files that already exist.
Your server could prepend the UUID to the filename:
4A0BC570-0125-11E3-B778-0800200C9A66_image.jpg
or create an entirely new folder:
4A0BC570-0125-11E3-B778-0800200C9A66/image.jpg
Not only will this ensure that users uploading on iOS don't overwrite each others' files, but it will also ensure that two users on any platform uploading two different files with the same name won't step on each others' toes.
If you have any server-/client-side code you'd like to share, I can take a peek, modify it and post in here with my answer.
Related
I would like to pause fineuploader if the document dropped is a pdf to give the end user some options before continuing. I cannot figure out how to get the pause to trigger. I am getting [Fine Uploader 5.3.2] Ignoring pause for file ID 0 (DEVELOPMENT.PDF). Not in progress.
My code below.
var uploader = new qq.s3.FineUploader({
debug: true,
element: document.getElementById('fine-uploader'),
request: {
endpoint: 'bucketname.s3.amazonaws.com',
accessKey: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' //zone-user key id
},
signature: {
endpoint: "/assets/plugins/fine-uploader/signature/endpoint.php"
},
debug:true,
cors: {expected: true},
chunking: {enabled: true},
resume: {enabled: true},
deleteFile:{enabled:false},
validation: {
itemLimit: 5,
sizeLimit: 15000000
},
uploadSuccess:{
//endpoint:"/assets/plugins/fine-uploader/signature/endpoint.php?success"
},
callbacks: {
onSubmitted: function(id, name) {
var fileName = name;
var fileExtension = fileName.substring(fileName.lastIndexOf('.') + 1).toUpperCase();
if(fileExtension==='PDF'){
alert('it IS pdf... now what?');
jQuery('#confirmPDFHandler').modal();
uploader.pauseUpload(id); //not pausing here
}else{
alert('its not a pdf... go!');
uploader.continueUpload(id);
}
},
onError: function(id, name, errorReason, xhrOrXdr) {
//alert(qq.format("Error on file number {} - {}. Reason: {}", id, name, errorReason));
},
onUpload: function(id, name, isError,responseJSON) {
var obj = JSON.stringify(responseJSON);
//alert(name + 'is in progress');
},
onComplete: function(id,fileId,responseJSON){
var newfilename=uploader.getKey(id);
}
},
retry: {enableAuto: false}
});
If the user drops a pdf in the uploader, we will give them an option to simply upload (continue as usual) or split the file (pause or stop the upload and run our separate custom code to begin the pdf split option pulling one document into multiple documents then passing those to an uploader)
Sounds like you want to potentially cancel the upload, or proceed. In that case, you should ask the user for input inside of an onSubmit or onValidate event handler. Your handler should return a Promise and either resolve the promise to allow the file to go through, or reject it to cancel the file submission. For example:
onSubmit: function(id) {
return new Promise(function(resolve, reject) {
// popup modal
// when user responds...
// ...call resolve() if they want to upload the file
// ...or reject() if they want to cancel the file
});
}
Fine Uploader has a very small "promise" implementation bundled with the library. It's non-standard, so you may be better off finding a standard A+ implementation instead.
I am using the dropzone js plugin to upload files to a php server. It is working great. I am facilitating the user to update the uploaded files. So once the user clicks on update button, the dropzone appears, and I am able to display the uploaded files in it through a JQuery-AJAX call. But my problem is that though the files are displayed in the thumbnail format, the number of files in the dropzone counts to zero. I feel that the accept function is not being triggered.But if a new file is added to the displaying list the file count is 1 though there are files already existing in it.
I am using the following code to display the files in dropzone:
var mockFile = { name: "Filename", size: 12345 };
myDropzone.options.addedfile.call(myDropzone, mockFile);
myDropzone.options.thumbnail.call(myDropzone, mockFile, "/image/url");
Can anyone help me solve this?
I think you need to push the mockFile in the dropZone manually like this
myDropzone.emit("addedfile", mockFile);
myDropzone.emit("complete", mockFile);
myDropzone.files.push(mockFile);
It's work for me... if you need more code just ask!
Mock file is not uploaded as explained here https://github.com/enyo/dropzone/issues/418
If you want to submit the form use myDropzone.uploadFiles([]); in init()
$('input[type="submit"]').on("click", function (e) {
e.preventDefault();
e.stopPropagation();
var form = $(this).closest('#dropzone-form');
if (form.valid() == true) { //trigger ASP.NET MVC validation
if (myDropzone.getQueuedFiles().length > 0) {
myDropzone.processQueue();
} else {
myDropzone.uploadFiles([]);
}
}
});
example for U!
jQuery(function($) {
//文件上传
$(".dropzone").dropzone({
url : "pic_upload.jsp?id=<%=request.getParameter("id")%>",
addRemoveLinks : true,
dictRemoveLinks : "x",
dictCancelUpload : "x",
maxFiles : 5,
maxFilesize : 5,
acceptedFiles: "image/*",
init : function() {
//上传成功处理函数
this.on("success", function(file) {
alert("修改前:"+file.name);
});
this.on("removedfile", function(file) {
alert("File " + file.name + "removed");
//ajax删除数据库的文件信息
$.ajax({
type:'post',
url:'pic_delete.jsp?id='+file.name ,
cache:false,
success:function(data){
}
});
});
<%
if(null!=list){
for(PlaceImg img:list){%>
//add already store files on server
var mockFile = { name: "<%=img.getId()%>", size: <%=img.getFilesize()%> };
// Call the default addedfile event handler
this.emit("addedfile", mockFile);
// And optionally show the thumbnail of the file:
this.emit("thumbnail", mockFile, "<%=img.getImgUrl()%>");
<%}
}%>
}
});
Say I want to upload several files at once, which is something I can do when setting the multiple option to true:
var myUploader = new qq.FineUploader({
element: $('#test')[0],
multiple: true,
request: { endpoint: 'path/to/master/server/php/' },
autoUpload: false,
});
Now, let's say I have a button that will allow me to select the files I want to upload. If I click said button and select, say, test.txt file, test.txt will be added to the list of files that will be uploaded. So far so good. Now, my problem is that, if I click the button again, and select test.txt file again, it will be added to the list even though it's already in the list.
Is there any way to prevent FineUploader from letting me do this?
Thanks in advance
I'd be careful declaring a file a duplicate simply based on the name. You should also take size into account, at least. Although, this is not possible in IE9 and older since we can't determine file size client-side in those browsers. Just for the purposes of simplicity, let's use the file name exclusively...
One way is to maintain an array of file names submitted to the uploader. You can add to this list in your an onSubmitted handler. The, you can contribute an onValidate handler that will reject the file if it already exists in the array. Your code would look something like this:
var filenames = [];
var myUploader = new qq.FineUploader({
element: $('#test')[0],
multiple: true,
request: { endpoint: 'path/to/master/server/php/' },
autoUpload: false,
callbacks: {
onSubmitted: function(id, name) {
filenames.push(name);
},
onValidate: function(fileData) {
return qq.indexOf(filenames, fileData.name) < 0;
}
}
});
Also, just for kicks, why not just use Fine Uploader's jQuery plug-in, since you seems to already be using jQuery in your project? The above example is rewritten using the jQuery plug-in below:
var filenames = [];
$('#test').fineUploader({
multiple: true,
request: { endpoint: 'path/to/master/server/php/' },
autoUpload: false
})
.on("submitted", function(event, id, name) {
filenames.push(name);
})
.on("validate", function(event, fileData) {
return $.inArray(fileData.name, filenames) < 0;
});
I have the following:
new qq.FileUploader({
element: $('#' + domid + ' #upload')[0],
action: '/api/panel/upload_file',
debug: true,
allowedExtensions: [
'jpg',
'jpeg',
'gif',
'png',
'bmp',
'pdf'
],
params: {
room : 'a_room',
module : 'a_module'
},
onSubmit: function(id, fileName) {
this.params.name = fileName;
},
onProgress: function(id, fileName, loaded, total) { },
onComplete : function(id, fileName, data) {
/* FINISH */
}
});
Which sends the upload request to:
case "api" :: "panel" :: "upload_file" :: Nil Post req => {
var response = true
req.body match {
case Full(file) =>
/* DO SOMETHING */
case _ => response = false
}
}
This works fine in both Firefox and Chrome, but when uploading with IE9 the file doesnt seem to get past:
req.body match {
case Full(file) =>
}
Is there something I'm missing or need to do to get this working properly?
Thanks in advance for any help, much appreciated :)
Firstly, req.body will give you an array of bytes, not a file. Lift will automatically detect if you're uploading a file or an arbitrary payload. Its not a good idea to put files into memory, especially if they might be large.
Look into req.uploadedFiles, and req.rawInputStream with OnDiskFileParamHolder.apply - if i recall how vallums uploader works, you have to manually push the input stream into the FileParamHolder, from which you can just call .file and then have a direct java.io.File instance to work with.
I'm using Plupload to allow multiple images to be uploaded to an mvc3 web app.
the files upload OK, but when i introduce the AntiForgeryToken it doesn't work, and the error is that no token was supplied, or it was invalid.
I also cannot get the Id parameter to be accepted as an action parameter either, it always sends null. So have to extract it myself from the Request.UrlReferrer property manually.
I figure plupload is submitting each file within the upload manually and forging its own form post.
My form....
#using (#Html.BeginForm("Upload", "Photo", new { Model.Id }, FormMethod.Post, new { id = "formUpload", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Id)
<div id="uploader">
<p>You browser doesn't have HTML5, Flash or basic file upload support, so you wont be able to upload any photos - sorry.</p>
</div>
<p id="status"></p>
}
and the code that wires it up...
$(document).ready(function ()
{
$("#uploader").plupload({
// General settings
runtimes: 'html5,flash,html4',
url: '/Photo/Upload/',
max_file_size: '8mb',
// chunk_size: '1mb',
unique_names: true,
// Resize images on clientside if we can
resize: { width: 400, quality: 100 },
// Specify what files to browse for
filters: [
{ title: "Image files", extensions: "jpg,gif,png" }
],
// Flash settings
flash_swf_url: 'Content/plugins/plupload/js/plupload.flash.swf'
});
$("#uploader").bind('Error', function(up, err)
{
$('#status').append("<b>Error: " + err.code + ", Message: " + err.message + (err.file ? ", File: " + err.file.name : "") + "</b>");
});
// Client side form validation
$('uploadForm').submit(function (e)
{
var uploader = $('#uploader').pluploadQueue();
// Validate number of uploaded files
if (uploader.total.uploaded == 0)
{
// Files in queue upload them first
if (uploader.files.length > 0)
{
// When all files are uploaded submit form
uploader.bind('UploadProgress', function ()
{
if (uploader.total.uploaded == uploader.files.length)
$('form').submit();
});
uploader.start();
} else
alert('You must at least upload one file.');
e.preventDefault();
}
});
});
and here is the controller action that receives it...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(int? id, HttpPostedFileBase file)
{
if (file.ContentLength > 0)
{
var parts = Request.UrlReferrer.AbsolutePath.Split('/');
var theId = parts[parts.Length - 1];
var fileName = theId + "_" + Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
}
return Content("Success", "text/plain");
}
As you can see, i have had to make the id parameter nullable, and i extract this manually in the action method.
How can i ensure that the values are sent with each form post correctly?
short answer : YES!
use multipart_params options like this:
multipart_params:
{
__RequestVerificationToken: $("#modal-dialog input[name=__RequestVerificationToken]").val()
}
short answer: you can't.
What you can do in this case is pass your token either as another multipart paramenter (if using that), or as part of the URL as a GET parameter, but nothing from the form will be sent by plupload as it builds its own request.
Another possibility is using custom headers to pass back the token to the server (plupload has a headers option), but whichever is the method you use, you will have to process it on your backend to validate it.